package com.gcloud.controller.compute.workflow.vm.senior.migrate;

import com.gcloud.controller.ResourceProviders;
import com.gcloud.controller.compute.dao.InstanceDao;
import com.gcloud.controller.compute.entity.VmInstance;
import com.gcloud.controller.compute.workflow.model.senior.migrate.MigrateAttachVolumeFlowCommandReq;
import com.gcloud.controller.compute.workflow.model.senior.migrate.MigrateAttachVolumeFlowCommandRes;
import com.gcloud.controller.storage.dao.VolumeAttachmentDao;
import com.gcloud.controller.storage.dao.VolumeDao;
import com.gcloud.controller.storage.entity.Volume;
import com.gcloud.controller.storage.entity.VolumeAttachment;
import com.gcloud.controller.storage.provider.IVolumeProvider;
import com.gcloud.controller.storage.service.IVolumeService;
import com.gcloud.core.workflow.core.BaseWorkFlowCommand;
import com.gcloud.header.enums.ResourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
/**
Copyright (c) [2020] [G-CLOUD TECHNOLOGY] [G-Cloud 8.0] is licensed under the Mulan PSL v1.
You can use this software according to the terms and conditions of the Mulan PSL v1. You may obtain
a copy of Mulan PSL v1 at: http://license.coscl.org.cn/MulanPSL THIS SOFTWARE IS PROVIDED ON AN 
"AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v1 for more details.
 */


@Component
@Scope("prototype")
@Slf4j
public class MigrateAttachVolumeFlowCommand extends BaseWorkFlowCommand{

	@Autowired
	private VolumeDao volumeDao;

	@Autowired
	private IVolumeService volumeService;

	@Autowired
	private VolumeAttachmentDao volumeAttachmentDao;

	@Autowired
	private InstanceDao instanceDao;

	@Override
	protected Object process() throws Exception {
		log.debug("MigrateAttachVolumeFlowCommand start");
		MigrateAttachVolumeFlowCommandReq req = (MigrateAttachVolumeFlowCommandReq) getReqParams();

		Volume volume = volumeDao.getById(req.getRepeatParams().getDiskId());

		VmInstance vmInstance = instanceDao.getById(req.getInstanceId());

		Map<String, Object> attachFilter = new HashMap<>();
		attachFilter.put(VolumeAttachment.INSTANCE_UUID, vmInstance.getId());
		attachFilter.put(VolumeAttachment.VOLUME_ID, volume.getId());
		attachFilter.put(VolumeAttachment.ATTACHED_HOST, req.getSourceHostName());

		VolumeAttachment attachment = volumeAttachmentDao.findUniqueByProperties(attachFilter);

		String volumeId = volume.getId();

		volumeService.reserveVolume(volumeId);
		String targetAttachmentId = null;
		try{
			targetAttachmentId = volumeService.attachVolume(volume.getId(), vmInstance.getId(), attachment.getMountpoint(), req.getTargetHostName(), getTaskId());
		}catch (Exception ex){
			log.error(String.format("::挂载失败, volumeId=%s", volumeId), ex);
			volumeService.unreserveVolume(volumeId);
			throw ex;
		}






		//磁盘信息，传出去，方便rollback
		MigrateAttachVolumeFlowCommandRes res = new MigrateAttachVolumeFlowCommandRes();
		res.setTargetAttachmentId(targetAttachmentId);

		log.debug("MigrateAttachVolumeFlowCommand end");
		return res;
	}

	@Override
	protected Object rollback() throws Exception {
		System.out.println(this.getClass().getSimpleName() + " rollback()");

		MigrateAttachVolumeFlowCommandReq req = (MigrateAttachVolumeFlowCommandReq)getReqParams();
		MigrateAttachVolumeFlowCommandRes res = (MigrateAttachVolumeFlowCommandRes)getResParams();

		volumeService.beginDetachingVolume(req.getRepeatParams().getDiskId());
		try{
			volumeService.detachVolume(req.getRepeatParams().getDiskId(), res.getTargetAttachmentId());
		}catch (Exception ex){
			log.error(String.format("::卸载失败, volumeId=%s", req.getRepeatParams().getDiskId()), ex);
			volumeService.rollDetachingVolume(req.getRepeatParams().getDiskId());
			throw ex;
		}

		return null;
	}

	@Override
	public boolean judgeExecute() {
		MigrateAttachVolumeFlowCommandReq req = (MigrateAttachVolumeFlowCommandReq)getReqParams();
		return req.getRepeatParams() != null;
	}

	@Override
	protected Object timeout() throws Exception {
		return null;
	}

	@Override
	protected Class<?> getReqParamClass() {
		return MigrateAttachVolumeFlowCommandReq.class;
	}

	@Override
	protected Class<?> getResParamClass() {
		return MigrateAttachVolumeFlowCommandRes.class;
	}
	
	private IVolumeProvider getVolumeProvider(int providerType) {
        IVolumeProvider provider = ResourceProviders.checkAndGet(ResourceType.VOLUME, providerType);
        return provider;
    }

}